﻿using System.IO;
using System.Linq;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.StorageClient;

namespace AMT.Azure.Metrics.Storage
{
	public class TransactionMetricsAccessor  // TODO: provide generic type?  PROB: no CloudTable obj<TStgType>
	{
		private const string DEFAULT_OUTPUT_FILE_TYPE = "csv"; //"json";

		private CloudStorageAccount _stgAcct;
		private bool _requireHttps = false;

		public TransactionMetricsAccessor(string stgAcctName, string stgAcctKey, bool requireHttps)
			:this(stgAcctName, stgAcctKey, requireHttps.ToString())
		{}

		public TransactionMetricsAccessor(string stgAcctName, string stgAcctKey, string requireHttps)
		{
			if (!bool.TryParse(requireHttps, out _requireHttps))
				_requireHttps = false;

			_stgAcct = new CloudStorageAccount(new StorageCredentialsAccountAndKey(stgAcctName, stgAcctKey), _requireHttps);
		}


		public bool BlobCapacityMetricsExist()
		{
			CloudTableClient cli = new CloudTableClient(_stgAcct.TableEndpoint, _stgAcct.Credentials);
			return cli.DoesTableExist(AMT.Azure.Metrics.Storage.Constants.BlobCapacityMetricsTableName);
		}

		public bool BlobTransactionMetricsExist()
		{
			CloudTableClient cli = new CloudTableClient(_stgAcct.TableEndpoint, _stgAcct.Credentials);
			return cli.DoesTableExist(AMT.Azure.Metrics.Storage.Constants.BlobTransactionMetricsTableName);
		}

		public bool TableTransactionMetricsExist()
		{
			CloudTableClient cli = new CloudTableClient(_stgAcct.TableEndpoint, _stgAcct.Credentials);
			return cli.DoesTableExist(AMT.Azure.Metrics.Storage.Constants.TableTransactionMetricsTableName);
		}

		public bool QueueTransactionMetricsExist()
		{
			CloudTableClient cli = new CloudTableClient(_stgAcct.TableEndpoint, _stgAcct.Credentials);
			return cli.DoesTableExist(AMT.Azure.Metrics.Storage.Constants.QueueTransactionMetricsTableName);
		}


		#region Methods for copying metrics to a local file
		
		public void CopyBlobCapacityMetricsToFile(string targetPath)
		{
			WriteMetricsToFile(targetPath, AMT.Azure.Metrics.Storage.Constants.BlobCapacityMetricsTableName);
		}


		public void CopyBlobTransactionsMetricsToFile(string targetPath)
		{
			WriteMetricsToFile(targetPath, AMT.Azure.Metrics.Storage.Constants.BlobTransactionMetricsTableName);
		}


		private FileInfo BuildFileInfo(string targetPath, string metricsIdentifier)
		{
			FileInfo fi = new FileInfo(targetPath);
			if (!fi.Exists && (null == fi.Extension || 0 == fi.Extension.Length))
			{
				// User passed a path w/o a filename & extension; need to create those
				string targetFile = string.Format("{0}.{1}", 
						metricsIdentifier.Replace('$', ' ').Trim(), 
						DEFAULT_OUTPUT_FILE_TYPE
					);
				fi = new FileInfo(Path.Combine(fi.DirectoryName, targetFile));
			}

			System.Diagnostics.Debug.Assert(null != fi.Extension);
			System.Diagnostics.Debug.Assert(0 < fi.Extension.Length);

			return fi;
		}


		private void WriteMetricsToFile(string targetPath, string metricsIdentifier)
		{
			System.Diagnostics.Debug.Assert(null != targetPath && 0 < targetPath.Length);
			System.Diagnostics.Debug.Assert(null != metricsIdentifier);

			TableServiceContext ctxt = (new CloudTableClient(_stgAcct.TableEndpoint, _stgAcct.Credentials)).GetDataServiceContext();

			FileInfo targetFile = BuildFileInfo(targetPath, metricsIdentifier);
			switch (metricsIdentifier)
			{
				case Constants.BlobCapacityMetricsTableName:
					WriteCapacityMetricsToFile(targetFile.FullName, ctxt, metricsIdentifier);
					break;

				case Constants.BlobTransactionMetricsTableName:
				case Constants.QueueTransactionMetricsTableName: 
				case Constants.TableTransactionMetricsTableName:
					WriteTransactionMetricsToFile(targetFile.FullName, ctxt, metricsIdentifier);
					break;

				default:
					System.Diagnostics.Debug.Assert(false, "Invalid metricsIdentifier value");
					break;
			}

		}


		private void WriteCapacityMetricsToFile(string targetFile, TableServiceContext ctxt, string metricsIdentifier)
		{
			CloudTableQuery<MetricsCapacityEntity> query = (from entity in ctxt.CreateQuery<MetricsCapacityEntity>(metricsIdentifier)
															select entity).AsTableServiceQuery<MetricsCapacityEntity>();

			WriteMetricsTofile<MetricsCapacityEntity>(targetFile, query);
		}


		private void WriteMetricsTofile<T>(string targetFile, CloudTableQuery<T> query)
		{
			switch (new FileInfo(targetFile).Extension.ToLower())
			{
				case ".csv":
					StorageMetricsSerializer<T>.SerializeCsv(targetFile, query);
					break;

				case ".xml":
					StorageMetricsSerializer<T>.SerializeXml(targetFile, query);
					break;

				case ".json":
					StorageMetricsSerializer<T>.SerializeJson(targetFile, query);
					break;

				// TODO: consider: just default to xml or json?
				default:
					throw new System.ArgumentException("The given file extension is not supported");
					break;
			}
		}

		private void WriteTransactionMetricsToFile(string targetFile, TableServiceContext ctxt, string metricsIdentifier)
		{
			CloudTableQuery<MetricsTransactionsEntity> query = (from entity in ctxt.CreateQuery<MetricsTransactionsEntity>(metricsIdentifier)
																select entity).AsTableServiceQuery<MetricsTransactionsEntity>();

			WriteMetricsTofile<MetricsTransactionsEntity>(targetFile, query);
		}


		#endregion
	}


}
